package com.venmo.android.pin;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.text.Editable;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.venmo.android.pin.util.VibrationHelper;
import com.venmo.android.pin.view.PinKeyboardView;
import com.venmo.android.pin.view.PinputView;
import com.venmo.android.pin.view.PinputView.OnCommitListener;
import java.util.concurrent.ExecutorService;
import static android.view.MotionEvent.ACTION_DOWN;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
abstract class BaseViewController<T extends PinFragmentImplement> {
private ExecutorService mExecutor;
protected T mPinFragment;
protected Context mContext;
protected PinputView mPinputView;
protected PinKeyboardView mKeyboardView;
protected TextView mHeaderText;
protected ProgressBar mProgressBar;
protected View mRootView;
/*package*/ BaseViewController(T f, View v) {
mPinFragment = f;
mContext = f.getContext();
mRootView = v;
init();
}
private void init() {
mPinputView = (PinputView) mRootView.findViewById(R.id.pin_pinputview);
mKeyboardView = (PinKeyboardView) mRootView.findViewById(R.id.pin_keyboard);
mProgressBar = (ProgressBar) mRootView.findViewById(R.id.pin_progress_spinner);
mHeaderText = (TextView) mRootView.findViewById(R.id.pin_header_label);
initKeyboard();
initUI();
mPinputView.setListener(provideListener());
}
final void refresh(View rootView) {
mRootView = rootView;
init();
}
abstract void initUI();
abstract OnCommitListener provideListener();
private void initKeyboard() {
mKeyboardView.setOnKeyboardActionListener(new PinKeyboardView.PinPadActionListener() {
@Override
public void onKey(int primaryCode, int[] keyCodes) {
Editable e = mPinputView.getText();
if (primaryCode == PinKeyboardView.KEYCODE_DELETE) {
int len = e.length();
if (len == 0) {
return;
}
e.delete(len - 1, e.length());
} else {
mPinputView.getText().append((char) primaryCode);
}
}
});
mKeyboardView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == ACTION_DOWN && getConfig().shouldVibrateOnKey()) {
VibrationHelper.vibrate(mContext, getConfig().vibrateDuration());
}
return false;
}
});
}
protected PinFragmentConfiguration getConfig() {
return mPinFragment.getConfig();
}
protected Animator getOutAnim(View v) {
float start = v.getX();
float end = -v.getWidth();
ObjectAnimator out = ObjectAnimator.ofFloat(v, "x", start, end);
out.setDuration(150);
out.setInterpolator(new AccelerateInterpolator());
return out;
}
protected Animator getInAnim(View v) {
float start = mRootView.getWidth();
float end = (start / 2) - (v.getWidth() / 2);
final ObjectAnimator in = ObjectAnimator.ofFloat(v, "x", start, end);
in.setDuration(150);
in.setInterpolator(new DecelerateInterpolator());
return in;
}
protected Animator getOutAndInAnim(final PinputView out, final View in) {
Animator a = getOutAnim(out);
a.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {}
@Override
public void onAnimationEnd(Animator animation) {
out.getText().clear();
in.setVisibility(View.VISIBLE);
getInAnim(in).start();
}
@Override
public void onAnimationCancel(Animator animation) {}
@Override
public void onAnimationRepeat(Animator animation) {}
});
return a;
}
void resetPinputView(){
mProgressBar.setVisibility(View.INVISIBLE);
float centerPosition = (mRootView.getWidth() / 2) - (mPinputView.getWidth() / 2);
mPinputView.setX(centerPosition);
mPinputView.getText().clear();
}
protected void runAsync(Runnable runnable) {
getExecutor().submit(runnable);
}
protected void postToMain(Runnable runnable) {
new Handler(Looper.getMainLooper()).post(runnable);
}
void generalErrorAsync(final String s){
postToMain(new Runnable() {
@Override
public void run() {
Toast.makeText(mContext, s, Toast.LENGTH_SHORT).show();
resetPinputView();
}
});
}
private ExecutorService getExecutor() {
if (mExecutor == null) {
mExecutor = newSingleThreadExecutor();
}
return mExecutor;
}
}